/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pro.unal.edu.datasource;

import java.awt.Color;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import pro.unal.edu.filter.MyPoint;

/**
 *
 * @author Carlos
 */
public final class TIFFImage extends MyImage {

    private static final int WIDTH = 256;
    private static final int HEIGHT = 257;
    private static final int COMPRESSION = 259;
    private static final int STRIP_OFFSETS = 273;
    private static final int SAMPLES_PER_PIXEL = 277;
    private static final int PLANAR_CONFIGURATION = 284;
    private static final int PREDICTOR = 317;
    private static final int TILE_WIDTH = 322;
    private static final int TILE_HEIGHT = 323;
    private static final int TILE_OFFSET = 324;
//    private Color[][] dataImageColor;
    /**
     * Info Header 14 data
     */
    private boolean exist = false;
    //2 data = 42
    private int isTiff;
    //LOS BYTES DEL ARCHIVO LEÍDO
    private byte[] bytesFile;
    //VARIABLES DEL TIFF
    private int endian;
    //Variables
    private int numTags;
    private int compression;

    public TIFFImage(String pathImage) {
        setPathImage(pathImage);
        loadImageProperties();
    }

    @Override
    protected void loadImageProperties() {
        try {
            /**** Load Image Properties****/
            BufferedInputStream is = new BufferedInputStream(new FileInputStream(getPathImage()));
            byte[] header = new byte[10240];
            is.read(header, 0, 1024);

            //2 data
            setSignature(((char) (readBytes(1, header, 0))) + "" + ((char) (readBytes(1, header, 1))));
            if ("MM".equalsIgnoreCase(getSignature())) {
                setLittleEndian(false);
            }
            //4 data
            isTiff = readBytes(2, header, 2);
            System.out.println("tiff: " + isTiff);
            //2 data
            setOffset(readBytes(2, header, 4));
            System.out.println("offset: " + getOffset());
            //2 data
            numTags = readBytes(2, header, getOffset());
            System.out.println("numTags: " + numTags);
            int stripOffsets = 0;
            int tagsCount = getOffset() + 2;
            int typeOfTag = 0;
            for (int i = 0; i < numTags; i++) {
                typeOfTag = readBytes(2, header, tagsCount);
                //height
                if (typeOfTag == HEIGHT) {
                    setHeight(readBytes(4, header, tagsCount + 8));
                    System.out.println("Height: " + getHeight());
                    //width
                } else if (typeOfTag == WIDTH) {
                    setWidth(readBytes(4, header, tagsCount + 8));
                    System.out.println("Width: " + getWidth());
                    //compression
                } else if (typeOfTag == COMPRESSION) {
                    compression = readBytes(4, header, tagsCount + 8);
                    if (compression == 1) {
                        System.out.println("TIFF sin compresion.");
                    } else if (compression == 5) {
                        System.out.println("TIFF con compresion LZW.");
                    } else {
                        System.out.println("TIFF con compresion no soportada.");
                    }
                    System.out.println("Compression: " + compression);
                } else if (typeOfTag == PREDICTOR) {
                    int predictor = readBytes(4, header, tagsCount + 8);
                    System.out.println("Predictor: " + predictor);
                } else if (typeOfTag == PLANAR_CONFIGURATION) {
                    int planar = readBytes(4, header, tagsCount + 8);
                    System.out.println("Planar configuration: " + planar);
                } else if (typeOfTag == SAMPLES_PER_PIXEL) {
                    int sPP = readBytes(4, header, tagsCount + 8);
                    System.out.println("Samples per pixel: " + sPP);
                } else if (typeOfTag == TILE_WIDTH) {
                    int tileWidth = readBytes(4, header, tagsCount + 8);
                    System.out.println("tileWidth: " + tileWidth);
                } else if (typeOfTag == TILE_HEIGHT) {
                    int tileHeight = readBytes(4, header, tagsCount + 8);
                    System.out.println("tileWidth: " + tileHeight);
                } else if (typeOfTag == TILE_OFFSET) {
                    int tileOffset = readBytes(4, header, tagsCount + 8);
                    System.out.println("Tiled: " + tileOffset);
                } else if (typeOfTag == STRIP_OFFSETS) {
                    stripOffsets = readBytes(4, header, tagsCount + 8);
//                    stripOffsets = 20520;
                    System.out.println("Strip Offsets: " + stripOffsets);
                } else if (typeOfTag == 258) {
                    int bitsPerSample = readBytes(4, header, tagsCount + 8);
//                    stripOffsets = 20520;
                    System.out.println("Bits Per Sample: " + bitsPerSample);
                }
                //avanzamos de tag en tag
                tagsCount += 12;
            }

            setDataImageColor(new Color[getWidth()][getHeight()]);

            /**** Load Image****/
            byte[] data = new byte[256 * getWidth() * getHeight()];
            is = new BufferedInputStream(new FileInputStream(getPathImage()));
            is.read(data, 0, 256 * getWidth() * getHeight());
            int x = 1;
            int y = getHeight() - 1;
            int i = stripOffsets;
            for (; x < getWidth() * getHeight(); i += 3) {
//                int a = 127;
                int b = 0;
                int g = 0;
                int r = 0;
                if (!isLittleEndian()) {
                    b = (data[i] + 256) % 256;
                    g = (data[i + 1] + 256) % 256;
                    r = (data[i + 2] + 256) % 256;
                } else {
                    r = (data[i] + 256) % 256;
                    g = (data[i + 1] + 256) % 256;
                    b = (data[i + 2] + 256) % 256;
                }
                Color c = new Color(r, g, b);
//                System.out.println(c);
                getDataImageColor()[(x - 1) % getWidth()][y] = c;
                if ((x % getWidth()) == 0) {
                    y--;
                }
                x++;
            }
            System.out.println("termino");
            is.close();


        } catch (FileNotFoundException ex) {
            Logger.getLogger(BMPImage.class.getName()).log(Level.SEVERE, null, ex);
            exist = false;
        } catch (IOException ex) {
            Logger.getLogger(BMPImage.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public byte[] CutBytes(byte[] b, int i, int j) {
        byte[] a = new byte[4];
        for (byte bb : a) {
            bb = 0;
        }
        int k = 0;

        for (int ii = i; ii < j; ii++) {
            a[k] = b[ii];
            k++;
        }

        return a;
    }
}
